import numpy as np
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
from pyod.models.lof import LOF
import matplotlib.font_manager
from pyod.models.ocsvm import OCSVM


def LocalOutlierFactorTest_2D(X, a, b):
    rng = np.random.RandomState(42)

    x_min = np.min(X[:, 0])
    x_max = np.max(X[:, 0])
    y_min = np.min(X[:, 1])
    y_max = np.max(X[:, 1])
    xx, yy = np.meshgrid(np.linspace(x_min - 0.8 * (x_max - x_min), x_max + 0.8 * (x_max - x_min), 150),
                         np.linspace(y_min - 0.8 * (y_max - y_min), y_max + 0.8 * (y_max - y_min), 150))
    if (X[:, 0] == np.arange(1, X.shape[0] + 1)).all:
        new_data = pd.DataFrame(X[:, 1], columns=['A'])
        plt.figure(figsize=(20, 16), dpi=80)
        plt.tick_params(labelsize=40)

        plt.scatter(X[:, 0], X[:, 1], s=1000)

        clf = LOF(n_neighbors=a, contamination=b)
        clf.fit(new_data)
        y_predict = clf.predict(new_data)

        y_train_pred = clf.labels_  # binary labels (0: inliers, 1: outliers)
        y_train_scores = clf.decision_scores_  # raw outlier scores
        product = np.where(y_train_pred)[0] + 1
        normal_product = np.where(y_train_pred == 0)[0]
        normal_value_min = np.repeat(X[normal_product, 1].min(), X.shape[0])
        normal_value_max = np.repeat(X[normal_product, 1].max(), X.shape[0])
        plt.plot(normal_value_min, 'red', linewidth=5)
        plt.plot(normal_value_max, 'red', linewidth=5)

        plt.title(u'包络线展示', fontproperties='Microsoft YaHei', fontsize=40)
        plt.xlabel(u'产品编号', fontproperties='Microsoft YaHei', fontsize=40)
        plt.ylabel(u'特征值', fontproperties='Microsoft YaHei', fontsize=40)
        plt.legend(['成功包络线'], prop=matplotlib.font_manager.FontProperties(size=20), loc='upper right')
        plt.tight_layout()
        plt.savefig("./img/LOF.png")
    else:

        new_data = pd.DataFrame(np.array(X), columns=['A', 'B'])

        plt.figure(figsize=(20, 16), dpi=80)
        plt.tick_params(labelsize=40)

        plt.scatter(X[:, 0], X[:, 1], s=1000)

        clf = LOF(n_neighbors=a, contamination=b)
        clf.fit(new_data)
        y_predict = clf.predict(new_data)
        n = clf.threshold_

        y_train_pred = clf.labels_  # binary labels (0: inliers, 1: outliers)
        y_train_scores = clf.decision_scores_  # raw outlier scores
        product = np.where(y_train_pred)[0] + 1
        # print("y_train_pred:",product.shape)
        # print("y_train_scores:  ", y_train_scores)
        # plt.title("LocalOutlierFactorTest")
        Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
        Z = Z.reshape(xx.shape)
        # 使用等高线画包络线
        CS = plt.contour(xx, yy, Z, levels=[n], linewidths=10, colors='red')
        # plt.ylim((-0.025,0.025))#设置轴y范围
        plt.title(u'包络线展示', fontproperties='Microsoft YaHei', fontsize=40)
        plt.xlabel(u'新特征1', fontproperties='Microsoft YaHei', fontsize=40)
        plt.ylabel(u'新特征2', fontproperties='Microsoft YaHei', fontsize=40)
        plt.legend([CS.collections[0]], ['成功包络线'], prop=matplotlib.font_manager.FontProperties(size=40),
                   loc='upper right')
        # CS.collections[0].set_label(u'成功包络线')
        plt.tight_layout()
        plt.legend(loc='upper right')
        plt.savefig("./img/LOF.png")
        # plt.show()
        # plt.close()
    return product


def OneclassSVMTest_2D(X, a, b):
    rng = np.random.RandomState(42)
    # Compare given classifiers under given settings
    x_min = np.min(X[:, 0])
    x_max = np.max(X[:, 0])
    y_min = np.min(X[:, 1])
    y_max = np.max(X[:, 1])
    xx, yy = np.meshgrid(np.linspace(x_min - 0.8 * (x_max - x_min), x_max + 0.8 * (x_max - x_min), 150),
                         np.linspace(y_min - 0.8 * (y_max - y_min), y_max + 0.8 * (y_max - y_min), 150))
    if (X[:, 0] == np.arange(1, X.shape[0] + 1)).all:
        new_data = pd.DataFrame(X[:, 1], columns=['A'])
        plt.figure(figsize=(20, 16), dpi=80)
        plt.tick_params(labelsize=40)

        plt.scatter(X[:, 0], X[:, 1], s=1000)

        clf = OCSVM(degree=a, contamination=b)
        clf.fit(new_data)
        y_predict = clf.predict(new_data)

        y_train_pred = clf.labels_  # binary labels (0: inliers, 1: outliers)
        y_train_scores = clf.decision_scores_  # raw outlier scores
        product = np.where(y_train_pred)[0] + 1
        normal_product = np.where(y_train_pred == 0)[0]
        normal_value_min = np.repeat(X[normal_product, 1].min(), X.shape[0])
        normal_value_max = np.repeat(X[normal_product, 1].max(), X.shape[0])
        plt.plot(normal_value_min, 'red', linewidth=5)
        plt.plot(normal_value_max, 'red', linewidth=5)

        plt.title(u'包络线展示', fontproperties='Microsoft YaHei', fontsize=40)
        plt.xlabel(u'产品编号', fontproperties='Microsoft YaHei', fontsize=40)
        plt.ylabel(u'特征值', fontproperties='Microsoft YaHei', fontsize=40)
        plt.legend(['成功包络线'], prop=matplotlib.font_manager.FontProperties(size=20), loc='upper right')
        plt.tight_layout()
        plt.savefig("./img/OneclassSVM.png")
    else:
        new_data = pd.DataFrame(np.array(X), columns=['A', 'B'])
        plt.figure(figsize=(20, 16), dpi=80)
        plt.tick_params(labelsize=40)
        plt.scatter(X[:, 0], X[:, 1], s=1000)

        n_num = len(X)
        clf_name = 'OneClassSVM'
        clf = OCSVM(degree=a, contamination=b)
        clf.fit(new_data)
        y_predict = clf.predict(new_data)
        m = clf.threshold_
        # get the prediction labels and outlier scores of the training data
        y_train_pred = clf.labels_  # binary labels (0: inliers, 1: outliers)
        y_train_scores = clf.decision_scores_  # raw outlier scores
        product = np.where(y_train_pred)[0] + 1
        # print("y_train_pred:",product.shape)
        # print("y_train_scores:  ", y_train_scores)
        # plt.title("LocalOutlierFactorTest")
        Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()])
        Z = Z.reshape(xx.shape)
        # 使用等高线画包络线
        CS = plt.contour(xx, yy, Z, levels=[m], linewidths=10, colors='red')
        # plt.ylim((-0.025,0.025))#设置轴y范围

        plt.title(u'包络线展示', fontproperties='Microsoft YaHei', fontsize=40)
        plt.xlabel(u'新特征1', fontproperties='Microsoft YaHei', fontsize=40)
        plt.ylabel(u'新特征2', fontproperties='Microsoft YaHei', fontsize=40)
        plt.legend([CS.collections[0]], ['成功包络线'], prop=matplotlib.font_manager.FontProperties(size=40),
                   loc='upper right')
        plt.tight_layout()
        plt.savefig("./img/OneclassSVM.png")
        product = np.where(y_train_pred)[0] + 1
    return product


def FeatureBaggingTest_2D(X, a, b):
    rng = np.random.RandomState(42)
    # Compare given classifiers under given settings
    x_min = np.min(X[:, 0])
    x_max = np.max(X[:, 0])
    y_min = np.min(X[:, 1])
    y_max = np.max(X[:, 1])
    xx, yy = np.meshgrid(np.linspace(x_min - 0.8 * (x_max - x_min), x_max + 0.8 * (x_max - x_min), 150),
                         np.linspace(y_min - 0.8 * (y_max - y_min), y_max + 0.8 * (y_max - y_min), 150))
    if (X[:, 0] == np.arange(1, X.shape[0] + 1)).all:
        new_data = pd.DataFrame(X[:, 1], columns=['A'])
        plt.figure(figsize=(20, 16), dpi=80)
        plt.tick_params(labelsize=40)

        plt.scatter(X[:, 0], X[:, 1], s=1000)
        n_num = len(X)
        clf_name0 = 'LOF'
        clf0 = LOF(n_neighbors=n_num // 2 + 1, contamination=0.1)
        clf0.fit(new_data)
        y_predict0 = clf0.predict(new_data)

        # get the prediction labels and outlier scores of the training data
        y_train_pred0 = clf0.labels_  # binary labels (0: inliers, 1: outliers)


        clf_name1 = 'OneClassSVM'
        clf1 = OCSVM()
        clf1.fit(new_data)
        y_predict1 = clf1.predict(new_data)
        # get the prediction labels and outlier scores of the training data
        y_train_pred1 = clf1.labels_  # binary labels (0: inliers, 1: outliers)
        y_train_pred = np.around(y_train_pred0 * a + y_train_pred1 * b)
        product = np.where(y_train_pred)[0] + 1
        normal_product = np.where(y_train_pred == 0)[0]
        normal_value_min = np.repeat(X[normal_product, 1].min(), X.shape[0])
        normal_value_max = np.repeat(X[normal_product, 1].max(), X.shape[0])
        plt.plot(normal_value_min, 'red', linewidth=5)
        plt.plot(normal_value_max, 'red', linewidth=5)

        plt.title(u'包络线展示', fontproperties='Microsoft YaHei', fontsize=40)
        plt.xlabel(u'产品编号', fontproperties='Microsoft YaHei', fontsize=40)
        plt.ylabel(u'特征值', fontproperties='Microsoft YaHei', fontsize=40)
        plt.legend(['成功包络线'], prop=matplotlib.font_manager.FontProperties(size=20), loc='upper right')
        plt.tight_layout()
        plt.savefig("./img/FeatureBagging.png")
    else:
        new_data = pd.DataFrame(np.array(X), columns=['A', 'B'])
        # print(plt.rcParams.get('figure.figsize'))
        plt.figure(figsize=(20, 16), dpi=80)
        plt.scatter(X[:, 0], X[:, 1], s=1000)

        n_num = len(X)

        clf_name0 = 'LOF'
        clf0 = LOF(n_neighbors=n_num // 2 + 1, contamination=0.1)
        clf0.fit(new_data)
        y_predict0 = clf0.predict(new_data)
        m = clf0.threshold_
        # get the prediction labels and outlier scores of the training data
        y_train_pred0 = clf0.labels_  # binary labels (0: inliers, 1: outliers)
        Z0 = clf0.decision_function(np.c_[xx.ravel(), yy.ravel()])
        Z0 = Z0.reshape(xx.shape)

        clf_name1 = 'OneClassSVM'
        clf1 = OCSVM()
        clf1.fit(new_data)
        y_predict1 = clf1.predict(new_data)
        n = clf1.threshold_
        # get the prediction labels and outlier scores of the training data
        y_train_pred1 = clf1.labels_  # binary labels (0: inliers, 1: outliers)
        Z1 = clf0.decision_function(np.c_[xx.ravel(), yy.ravel()])
        Z1 = Z1.reshape(xx.shape)

        Z = Z0 * a + Z1 * b
        y_train_pred = np.around(y_train_pred0 * a + y_train_pred1 * b)
        # 使用等高线画包络线
        CS = plt.contour(xx, yy, Z, levels=[m], linewidths=10, colors='red', label='three')
        plt.title(u'包络线展示', fontproperties='Microsoft YaHei', fontsize=40)
        plt.xlabel(u'新特征1', fontproperties='Microsoft YaHei', fontsize=40)
        plt.ylabel(u'新特征2', fontproperties='Microsoft YaHei', fontsize=40)
        plt.legend([CS.collections[0]], ['成功包络线'], prop=matplotlib.font_manager.FontProperties(size=40),
                   loc='upper right')
        plt.tight_layout()

        plt.savefig("./img/FeatureBagging.png")

        product = np.where(y_train_pred)[0] + 1
    return product


if __name__ == '__main__':
    plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
    plt.rcParams['axes.unicode_minus'] = False
    x = np.load('./predict_result/reduction_features.npy')
    FeatureBaggingTest_2D(x, 10, 0.1)
